"""DNS解析器."""

import asyncio
import logging
from typing import List, Optional, Dict, Any
import re

from sqlalchemy import select, and_
from sqlalchemy.ext.asyncio import AsyncSession

from netsphere.models.dns import DNSRecord, DNSZone
from netsphere.models.ipam import IPAddress

logger = logging.getLogger(__name__)


class DNSResolver:
    """DNS解析器，提供DNS查询功能."""
    
    def __init__(self, session: AsyncSession):
        """初始化DNS解析器.
        
        Args:
            session: 数据库会话
        """
        self.session = session
    
    async def resolve(
        self,
        name: str,
        record_type: str = "A",
        zone_name: str = None,
    ) -> List[DNSRecord]:
        """解析DNS记录.
        
        Args:
            name: 域名
            record_type: 记录类型
            zone_name: 指定区域名称（可选）
            
        Returns:
            DNS记录列表
        """
        # 规范化域名
        name = self._normalize_name(name)
        
        # 查找匹配的区域
        zones = await self._find_matching_zones(name, zone_name)
        if not zones:
            return []
        
        records = []
        for zone in zones:
            zone_records = await self._resolve_in_zone(name, record_type, zone)
            records.extend(zone_records)
        
        return records
    
    async def reverse_lookup(
        self,
        ip_address: str,
        zone_name: str = None,
    ) -> List[DNSRecord]:
        """反向DNS查询.
        
        Args:
            ip_address: IP地址
            zone_name: 指定区域名称（可选）
            
        Returns:
            PTR记录列表
        """
        # 生成反向查询域名
        reverse_name = self._get_reverse_name(ip_address)
        
        return await self.resolve(reverse_name, "PTR", zone_name)
    
    def _normalize_name(self, name: str) -> str:
        """规范化域名.
        
        Args:
            name: 域名
            
        Returns:
            规范化后的域名
        """
        name = name.lower().strip()
        if name.endswith("."):
            name = name[:-1]
        return name
    
    def _get_reverse_name(self, ip_address: str) -> str:
        """获取反向查询域名.
        
        Args:
            ip_address: IP地址
            
        Returns:
            反向查询域名
        """
        # 处理IPv4地址
        if "." in ip_address:
            parts = ip_address.split(".")
            return ".".join(reversed(parts)) + ".in-addr.arpa"
        
        # 处理IPv6地址
        elif ":" in ip_address:
            # 简化的IPv6反向查询
            return "ip6.arpa"  # 实际应用中需要完整转换
        
        return ""
    
    async def _find_matching_zones(
        self,
        name: str,
        zone_name: str = None,
    ) -> List[DNSZone]:
        """查找匹配的区域.
        
        Args:
            name: 域名
            zone_name: 指定区域名称
            
        Returns:
            匹配的区域列表
        """
        query = select(DNSZone).where(DNSZone.is_active == True)
        
        if zone_name:
            query = query.where(DNSZone.name == zone_name)
        
        result = await self.session.execute(query)
        zones = list(result.scalars().all())
        
        # 查找最长匹配的区域
        matching_zones = []
        for zone in zones:
            if name == zone.name or name.endswith("." + zone.name):
                matching_zones.append(zone)
        
        # 按区域名称长度排序（最长的优先）
        matching_zones.sort(key=lambda z: len(z.name), reverse=True)
        
        return matching_zones
    
    async def _resolve_in_zone(
        self,
        name: str,
        record_type: str,
        zone: DNSZone,
    ) -> List[DNSRecord]:
        """在指定区域内解析记录.
        
        Args:
            name: 域名
            record_type: 记录类型
            zone: DNS区域
            
        Returns:
            DNS记录列表
        """
        # 计算相对域名
        relative_name = name
        if name.endswith("." + zone.name):
            relative_name = name[:-(len(zone.name) + 1)]
        elif name == zone.name:
            relative_name = "@"
        
        # 查询记录
        query = select(DNSRecord).where(
            and_(
                DNSRecord.zone_id == zone.id,
                DNSRecord.name == relative_name,
                DNSRecord.record_type == record_type,
                DNSRecord.is_active == True
            )
        )
        
        result = await self.session.execute(query)
        records = list(result.scalars().all())
        
        # 处理CNAME链
        if record_type != "CNAME":
            cname_records = await self._resolve_in_zone(name, "CNAME", zone)
            for cname in cname_records:
                # 递归解析CNAME目标
                target_records = await self._resolve_in_zone(
                    cname.value, record_type, zone
                )
                records.extend(target_records)
        
        return records
    
    async def get_zone_records(
        self,
        zone_id: int,
        record_type: str = None,
    ) -> List[Dict[str, Any]]:
        """获取区域的所有记录.
        
        Args:
            zone_id: 区域ID
            record_type: 记录类型（可选）
            
        Returns:
            记录信息列表
        """
        query = select(DNSRecord).where(
            and_(
                DNSRecord.zone_id == zone_id,
                DNSRecord.is_active == True
            )
        )
        
        if record_type:
            query = query.where(DNSRecord.record_type == record_type)
        
        result = await self.session.execute(query)
        records = list(result.scalars().all())
        
        return [
            {
                "id": record.id,
                "name": record.name,
                "type": record.record_type,
                "value": record.value,
                "ttl": record.ttl,
                "priority": record.priority,
                "is_active": record.is_active,
                "created_at": record.created_at,
                "updated_at": record.updated_at,
            }
            for record in records
        ]
    
    async def validate_record_format(
        self,
        record_type: str,
        value: str,
    ) -> bool:
        """验证记录格式.
        
        Args:
            record_type: 记录类型
            value: 记录值
            
        Returns:
            是否有效
        """
        if record_type == "A":
            # IPv4地址验证
            pattern = r"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"
            return bool(re.match(pattern, value))
        
        elif record_type == "AAAA":
            # IPv6地址验证
            pattern = r"^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$"
            return bool(re.match(pattern, value))
        
        elif record_type == "CNAME":
            # CNAME验证
            return len(value) > 0 and " " not in value
        
        elif record_type == "MX":
            # MX记录验证
            parts = value.split()
            if len(parts) != 2:
                return False
            
            priority, domain = parts
            try:
                int(priority)
                return len(domain) > 0
            except ValueError:
                return False
        
        elif record_type == "TXT":
            # TXT记录验证
            return len(value) > 0
        
        elif record_type == "PTR":
            # PTR记录验证
            return len(value) > 0 and " " not in value
        
        return True